<?php

class Trie {
    /**
     * 采取关键词生成trie树，逐行全部匹配
     */
    private $root = array(
        'depth' => 0,       //树深度
        'next' => array(),  //下一节点
    );
    public $matched = array(); //匹配结果
    public $temp = ''; //临时变量

    /**
     * 关键词加入
     */
    public function append($keyword) {
		$words = preg_split('/(?<!^)(?!$)/u', $keyword); //拆分逐个字
        array_push($words, '`'); //尾部添加截断符
        $this->insert($this->root, $words);
    }

    /**
     * 开始匹配
     */
    public function match($str) {
        $words = preg_split('/(?<!^)(?!$)/u', $str);
       	while (count($words) > 0) {
            $res = $this->query($this->root, $words);
            if ($res) {
            	//关键词找到，将信息剪短(可以根据业务，看是否将信息剪短，在6万条数据下，可以加快0.1s)
            	// for($i = 0 ; $i < count($this->temp);$i++){
            	// 	 array_shift($words);
            	// }
            	if(isset($this->matched[$this->temp])){
            		$this->matched[$this->temp] ++ ;
            	}else{
            		$this->matched[$this->temp] = 1;
            	}
            }
            $this->temp = '';
            array_shift($words);
        }
    }

    /**
     * 构造trie树
     */
    private function insert(&$node, $words) {
        if (empty($words)) {
            return;
        }
        $word = array_shift($words);
        if (isset($node['next'][$word])) {
            $this->insert($node['next'][$word], $words);
        } else {
            $tmp_node = array(
                'depth' => $node['depth'] + 1,  //深度，在此类中暂时没用到，但其他业务可能很有用
                'next' => array(),  //下一节点
            );
            $node['next'][$word] = $tmp_node;
            $this->insert($node['next'][$word], $words);
        }
    }

    /**
     * 匹配过程
     */
    private function query($node, $words) {
        $word = array_shift($words);
        if (isset($node['next'][$word])) {
        	$this->temp .= $word;
            if (isset($node['next'][$word]['next']['`'])) {
                return true;
            }
            return $this->query($node['next'][$word], $words); //循环匹配下一节点
        } else {
            return false;
        }
    }

    /**
     * 匹配过程
     */
    public function printResult(){
    	print_r($this->matched);
    }
}

$keyWords = array(
	'进程',
	'服务',
	'启动时间',
	'内存损耗',
	'时间构造',
	'守护进程',
	'消息处理进程',
	'服务封装为接口给外部调用',
	'进程间通信',
);

$tree = new Trie();
foreach ($keyWords as $word) {
	$tree->append($word);
}

$file_path = "log.txt";
if(file_exists($file_path)){
	$file_arr = file($file_path);
	for($i=0;$i<count($file_arr);$i++){//逐行读取文件内容
		$tree->match($file_arr[$i]); //逐行匹配
	}
}

//输出结果
$tree->printResult();
